
//-----------------MATRICES---------------
float4x4 xWorld: World;				
float4x4 xView: View;
float4x4 xProjection: Projection;
float4x4 xRotationMatrix;



//-----------------TEXTURES---------------

Texture xTexture;
sampler ColoredTextureSampler = sampler_state { texture = <xTexture> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = wrap; AddressV = wrap;};

Texture xBlurMap;
sampler BlurMapSampler = sampler_state { texture = <xBlurMap> ;
    magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = wrap; AddressV = wrap;};
    
textureCUBE xCubeShadowMap; 
samplerCUBE CubeShadowMapSampler = sampler_state
{
	Texture = <xCubeShadowMap>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = wrap;
    AddressV = wrap;
};

textureCUBE xReflectionCube; 
samplerCUBE ReflectionCubeSampler = sampler_state
{
	Texture = <xReflectionCube>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    AddressU = wrap;
    AddressV = wrap;
};


//--------------- CONSTANTS ---------------



float4 xLightPosition;
float4 xAmbientLight;
float4 xCameraPosition;

float xReflectionIntensity;

float xSpecularFactor;

float xFieldOfView;
float xBlurFactor;
float xSpecularPower;
float4 xSpecularColor;



//------------------- STRUCTS -------------------   


struct BufferToVertex
{
float3 Pos : POSITION;
float4 Normal : NORMAL;
float4 UV : TEXCOORD0;

};


struct VertexToPixel
{
float4 Pos:POSITION;
float4 Orig_Pos:TEXCOORD1;
float4 UV:TEXCOORD0;
float4 Normal: TEXCOORD2;
float4 TexWeights: TEXCOORD3;
float4 Pos3D:TEXCOORD4;
float4 Pos2D:TEXCOORD5;
};


struct PixelToFrame
{
float4 Color:COLOR;
float Depth:DEPTH;
};

struct BufferToVertexT2S
{
float3 Pos : POSITION;
float4 UV : TEXCOORD0;

};



struct VertexToPixelT2S
{
float4 Pos:POSITION;
float4 UV:TEXCOORD0;
float4 Pos2D:TEXCOORD1;
};


struct PixelToFrameT2S
{
float4 Color:COLOR;
};


struct PSCubeIn
{
    float4 oPositionLight : POSITION;
    float3 lightVec       : TEXCOORD0;
};



//---------------------- HELPERS ------------------------

bool IsInShadow(float3 LightPos, float3 inObjPos)
{
     float4 PLightDirection = 0.0f;
     PLightDirection.xyz = LightPos.xyz - inObjPos;
     float distance = length(PLightDirection.xyz);
     PLightDirection.xyz = PLightDirection.xyz / distance;
     
    
     //sample depth from cubic shadow map                         		 
	 float shadowMapDepth = texCUBE(CubeShadowMapSampler, float4(-(PLightDirection.xyz), 0.0f)).r;
	 //depth comparison
	 if(distance > shadowMapDepth)   return true;	      	
	 else return false;
}

float4 BlurredSample(float2 UV)
{
 float d = 0.01f;
 float4 Sample=tex2D(ColoredTextureSampler, UV);
 float4 S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(d,d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(-d,d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(d,-d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(-d,-d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(0.0,d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(0.0,-d));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(d,0.0));
 Sample+=S2;
 S2=tex2D(ColoredTextureSampler, UV+float2(-d,0.0));
 Sample+=S2;
 Sample/=9.0f;
 return Sample;
}
 
 
 
 
 


//---------------------- SHADERS ------------------------


// ---- CUBE DEPTH --------------------------------

PSCubeIn cubedepthVS( float4 inPosition : POSITION )
{
    PSCubeIn output;

    float4x4 WorldViewProj;
    WorldViewProj=mul(xWorld,xView);
    WorldViewProj=mul(WorldViewProj,xProjection);
    
    float4 positionW = mul( inPosition, xWorld );
    output.oPositionLight = mul( inPosition, WorldViewProj );
    
    output.lightVec = xLightPosition.xyz - positionW.xyz; 

    return output;
}  

float4 cubedepthPS( PSCubeIn In ) : COLOR0
{
    float3 Color=float3(1,1,1)*(length(In.lightVec) + 0.2f);
	return float4(Color.xyz,1); 
   
} 

//---------- TEXTURE TO SCREEN ---------------

VertexToPixelT2S T2SVS(BufferToVertexT2S IN)
{
  VertexToPixelT2S OUT = (VertexToPixelT2S)0;
  OUT.Pos=float4(IN.Pos.xyz,1.0);
  OUT.Pos2D=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  return OUT;
}

PixelToFrameT2S T2SPS(VertexToPixelT2S IN) 
{
PixelToFrameT2S OUT = (PixelToFrameT2S)0;

float4 res=tex2D(ColoredTextureSampler, IN.UV);
float4 res2=BlurredSample(IN.UV);
float4 blurfactor=tex2D(BlurMapSampler,IN.UV);
float4 C=res2*blurfactor.x+res*(1-blurfactor.x);
OUT.Color=C;
return OUT;
}



//---------- BLUR MAP ---------------

VertexToPixel blurmapVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
	return OUT;
}

PixelToFrame blurmapPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float b=IN.Pos2D.z-xFieldOfView;
b*=b;
b*=xBlurFactor;
OUT.Color = float4(b,b,b,0);
return OUT;
}


//---------- TEXTURED ---------------

VertexToPixel texturedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
	return OUT;
}

PixelToFrame texturedPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;

float3 L =xLightPosition.xyz - IN.Pos3D.xyz;
L=normalize(L);
float3 Nm = mul(IN.Normal.xyz,xRotationMatrix);
Nm=normalize(Nm);
float LightIntensity = dot(Nm,L);
float3 EyeVec=normalize(xCameraPosition.xyz-IN.Pos3D.xyz);
//float3 R=2*dot(Nm,EyeVec)*Nm;
//R=R-EyeVec;
   float3 R=2*dot(Nm,L)*Nm;
   R=R-L;
R=normalize(R);
float SI=dot(R,EyeVec);
SI=pow(SI,xSpecularPower);
if (IsInShadow(xLightPosition,IN.Pos3D.xyz)) {LightIntensity=0.1f; }//SI=0.0f;}
if (LightIntensity<0.1f) LightIntensity=0.1f;

float4 color=tex2D(ColoredTextureSampler, IN.UV)*LightIntensity+xSpecularColor*SI*xSpecularFactor;
OUT.Color = saturate(color+xAmbientLight);
return OUT;
}

//---------- TEXTURED with REFLECTIONS---------------

VertexToPixel texturedrefVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
	return OUT;
}

PixelToFrame texturedrefPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;

float3 L =xLightPosition.xyz - IN.Pos3D.xyz;
L=normalize(L);
float3 Nm = mul(IN.Normal.xyz,xRotationMatrix);
Nm=normalize(Nm);
float LightIntensity = dot(Nm,L);
float3 EyeVec=normalize(xCameraPosition.xyz-IN.Pos3D.xyz);
//float3 R=2*dot(Nm,EyeVec)*Nm;
//R=R-EyeVec;
   float3 R=2*dot(Nm,L)*Nm;
   R=R-L;
R=normalize(R);
float SI=dot(R,EyeVec);
SI=pow(SI,xSpecularPower);
if (IsInShadow(xLightPosition,IN.Pos3D.xyz)) {LightIntensity=0.1f; }//SI=0.0f;}
if (LightIntensity<0.1f) LightIntensity=0.1f;

float4 color=tex2D(ColoredTextureSampler, IN.UV)*LightIntensity+xSpecularColor*SI*xSpecularFactor;
OUT.Color = saturate(color+xAmbientLight);
return OUT;
}

//---------- REFLECTIONS---------------

VertexToPixel reflectedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
	return OUT;
}

PixelToFrame reflectedPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
float3 L =xLightPosition.xyz - IN.Pos3D.xyz;
L=normalize(L);
float3 Nm = mul(IN.Normal.xyz,xRotationMatrix);
Nm=normalize(Nm);
float LightIntensity = dot(Nm,L);
float3 EyeVec=normalize(xCameraPosition.xyz-IN.Pos3D.xyz);
//float3 R=2*dot(Nm,EyeVec)*Nm;
//R=R-EyeVec;
   float3 R=2*dot(Nm,L)*Nm;
   R=R-L;
R=normalize(R);
float SI=dot(R,EyeVec);
SI=pow(SI,xSpecularPower);
float4 refcolor=texCUBE(ReflectionCubeSampler,R)*xReflectionIntensity;
if (IsInShadow(xLightPosition,IN.Pos3D.xyz)) {LightIntensity=0.1f; SI=0.0f;}
if (LightIntensity<0.1f) LightIntensity=0.1f;
float4 color=refcolor*LightIntensity + xSpecularColor*SI*xSpecularFactor;
OUT.Color = saturate(color+xAmbientLight);
//OUT.Color = refcolor;
return OUT;
}



//----------- TEXTURED (NO LIGHTING) ----------
VertexToPixel nolighttexturedVS(BufferToVertex IN)
{
  VertexToPixel OUT = (VertexToPixel)0;
  float4x4 WorldViewProj;
  WorldViewProj=mul(xWorld,xView);
  WorldViewProj=mul(WorldViewProj,xProjection);
  OUT.Pos=mul(float4(IN.Pos.xyz,1.0), WorldViewProj);
  OUT.Pos2D=OUT.Pos;
  OUT.Pos3D=mul(float4(IN.Pos.xyz,1.0),xWorld);
  OUT.Orig_Pos=float4(IN.Pos.xyz,1.0);
  OUT.UV=float4(IN.UV.xy,1.0,1.0);
  OUT.Normal=IN.Normal;
  return OUT;
}

PixelToFrame nolighttexturedPS(VertexToPixel IN) 
{
PixelToFrame OUT = (PixelToFrame)0;
OUT.Depth=IN.Pos2D.z/IN.Pos2D.w;
OUT.Color = saturate(tex2D(ColoredTextureSampler, IN.UV)+xAmbientLight);

return OUT;
}




// ------------ TECHNIQUES --------------

technique nolighttextured {
	pass p0 {
		VertexShader = compile vs_3_0 nolighttexturedVS();
		PixelShader = compile ps_3_0 nolighttexturedPS();
	}
}

technique textured {
	pass p0 {
		VertexShader = compile vs_3_0 texturedVS();
		PixelShader = compile ps_3_0 texturedPS();
	}
}

technique texturedref {
	pass p0 {
		VertexShader = compile vs_3_0 texturedrefVS();
		PixelShader = compile ps_3_0 texturedrefPS();
	}
}

technique reflected {
	pass p0 {
		VertexShader = compile vs_3_0 reflectedVS();
		PixelShader = compile ps_3_0 reflectedPS();
	}
}

technique blurmap {
	pass p0 {
		VertexShader = compile vs_3_0 blurmapVS();
		PixelShader = compile ps_3_0 blurmapPS();
	}
}

technique cubedepth{
	pass p0 {
		
		VertexShader = compile vs_3_0 cubedepthVS();
		PixelShader = compile ps_3_0 cubedepthPS();
	}
}

technique T2S{
	pass p0 {
		
		VertexShader = compile vs_3_0 T2SVS();
		PixelShader = compile ps_3_0 T2SPS();
	}
}